using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using ItemStatsSystem;
using ItemHelperLib.Define;
using ItemHelperLib.Util;
using Newtonsoft.Json;

namespace CustomItemLib
{
    // 自定义属性提供者接口
    // 用于为自定义物品提供自定义属性
    public interface ICustomPropertyProvider
    {
        // 应用自定义属性到物品
        void ApplyCustomProperties(Item item, CustomItemData data);
    }

    /// <summary>
    /// JSON配置根对象包装器（用于 Unity JsonUtility）
    /// </summary>
    [Serializable]
    public class ItemConfigRoot<T> where T : CustomItemData
    {
        public T[] items = Array.Empty<T>();
    }

    // 自定义物品工厂类
    // 负责创建和配置自定义物品
    public class CustomItemFactory
    {
        // 存储已注册的自定义属性提供者，按CustomItemData类型分组
        private static readonly Dictionary<Type, List<ICustomPropertyProvider>> typeSpecificProviders = new Dictionary<Type, List<ICustomPropertyProvider>>();

        // 存储通用的自定义属性提供者（适用于所有物品类型）
        private static readonly List<ICustomPropertyProvider> genericProviders = new List<ICustomPropertyProvider>();

        #region 自定义属性提供者管理

        // 注册适用于特定CustomItemData类型的自定义属性提供者
        public static void RegisterCustomPropertyProvider<T>(ICustomPropertyProvider provider) where T : CustomItemData
        {
            if (provider == null)
            {
                Debug.LogError("[CustomItemLib] 尝试注册空的自定义属性提供者");
                return;
            }

            Type dataType = typeof(T);

            // 为指定类型的CustomItemData注册提供者
            if (!typeSpecificProviders.TryGetValue(dataType, out List<ICustomPropertyProvider>? providers))
            {
                providers = new List<ICustomPropertyProvider>();
                typeSpecificProviders[dataType] = providers;
            }

            if (providers.Contains(provider))
            {
                Debug.LogWarning($"[CustomItemLib] 自定义属性提供者 {provider.GetType().Name} 已为 {dataType.Name} 类型注册，跳过重复注册");
                return;
            }

            providers.Add(provider);
            Debug.Log($"[CustomItemLib] 成功注册自定义属性提供者: {provider.GetType().Name} 用于 {dataType.Name}");
        }

        // 注册适用于所有CustomItemData类型的通用自定义属性提供者
        public static void RegisterGenericPropertyProvider(ICustomPropertyProvider provider)
        {
            if (provider == null)
            {
                Debug.LogError("[CustomItemLib] 尝试注册空的通用自定义属性提供者");
                return;
            }

            if (genericProviders.Contains(provider))
            {
                Debug.LogWarning("[CustomItemLib] 通用自定义属性提供者已注册，跳过重复注册");
                return;
            }

            genericProviders.Add(provider);
            Debug.Log($"[CustomItemLib] 成功注册通用自定义属性提供者: {provider.GetType().Name}");
        }

        // 取消注册特定CustomItemData类型的自定义属性提供者
        public static void UnregisterCustomPropertyProvider<T>(ICustomPropertyProvider provider) where T : CustomItemData
        {
            if (provider == null)
            {
                Debug.LogError("[CustomItemLib] 尝试取消注册空的自定义属性提供者");
                return;
            }

            Type dataType = typeof(T);

            if (typeSpecificProviders.TryGetValue(dataType, out List<ICustomPropertyProvider>? providers))
            {
                if (providers.Remove(provider))
                {
                    Debug.Log($"[CustomItemLib] 成功取消注册自定义属性提供者: {provider.GetType().Name} 从 {dataType.Name}");

                    // 如果列表为空，删除该类型的条目
                    if (providers.Count == 0)
                    {
                        typeSpecificProviders.Remove(dataType);
                    }
                }
                else
                {
                    Debug.LogWarning($"[CustomItemLib] 未找到 {dataType.Name} 类型中注册的自定义属性提供者: {provider.GetType().Name}");
                }
            }
            else
            {
                Debug.LogWarning($"[CustomItemLib] 未找到 {dataType.Name} 类型的自定义属性提供者列表");
            }
        }

        // 取消注册通用自定义属性提供者
        public static void UnregisterGenericPropertyProvider(ICustomPropertyProvider provider)
        {
            if (provider == null)
            {
                Debug.LogError("[CustomItemLib] 尝试取消注册空的通用自定义属性提供者");
                return;
            }

            if (genericProviders.Remove(provider))
            {
                Debug.Log($"[CustomItemLib] 成功取消注册通用自定义属性提供者: {provider.GetType().Name}");
            }
            else
            {
                Debug.LogWarning($"[CustomItemLib] 未找到通用自定义属性提供者: {provider.GetType().Name}");
            }
        }

        // 清除所有自定义属性提供者
        public static void ClearCustomPropertyProviders()
        {
            typeSpecificProviders.Clear();
            genericProviders.Clear();
            Debug.Log("[CustomItemLib] 已清除所有自定义属性提供者");
        }

        // 清除特定CustomItemData类型的所有自定义属性提供者
        public static void ClearPropertyProvidersForType<T>() where T : CustomItemData
        {
            Type dataType = typeof(T);

            if (typeSpecificProviders.Remove(dataType))
            {
                Debug.Log($"[CustomItemLib] 已清除 {dataType.Name} 类型的所有自定义属性提供者");
            }
            else
            {
                Debug.Log($"[CustomItemLib] 未找到 {dataType.Name} 类型的自定义属性提供者");
            }
        }

        #endregion

        // 创建自定义物品的 GameObject 和 Item 组件
        // 根据 CustomItemData 的所有可选属性进行配置
        public static Item? CreateCustomItem(CustomItemData data)
        {
            // ==================== 1. 从模板获取 Prefab 并克隆 ====================
            Item templatePrefab = ItemAssetsCollection.GetPrefab(data.TemplateTypeID);

            if (templatePrefab == null)
            {
                Debug.LogError($"[CustomItemLib] 无法找到模板物品 (TemplateTypeID: {data.TemplateTypeID})");
                return null;
            }

            // 克隆模板物品作为新的 Prefab（不是场景实例）
            Item item = UnityEngine.Object.Instantiate(templatePrefab);

            if (item == null)
            {
                Debug.LogError($"[CustomItemLib] 克隆模板物品失败 (TemplateTypeID: {data.TemplateTypeID})");
                return null;
            }

            // 标记为 DontDestroyOnLoad，使其成为持久的 prefab
            UnityEngine.Object.DontDestroyOnLoad(item.gameObject);

            // ==================== 2. 设置必需属性 ====================
            // typeID 只有 internal setter，需要通过反射访问私有字段
            ItemHelper.SetItemProperty(item, ItemPrivateField.typeID, data.NewTypeID);

            // ==================== 3. 设置展示相关属性 ====================

            // 显示名称(DisplayNameRaw)
            if (!string.IsNullOrEmpty(data.DisplayName))
                ItemHelper.SetItemProperty(item, ItemSettableProperty.DisplayNameRaw, data.DisplayName);

            // 图标(Icon)
            if (data.Icon != null)
                ItemHelper.SetItemProperty(item, ItemSettableProperty.Icon, data.Icon);

            // 排序值(Order)- 如果未指定则使用 TemplateTypeID
            if (data.Order.HasValue)
                ItemHelper.SetItemProperty(item, ItemSettableProperty.Order, data.Order.Value);

            // ==================== 4. 设置堆叠相关属性 ====================

            // 最大堆叠数量(MaxStackCount)- 默认为1(不可堆叠)
            if (data.MaxStackCount.HasValue)
                ItemHelper.SetItemProperty(item, ItemSettableProperty.MaxStackCount, data.MaxStackCount.Value);

            // 堆叠数量(StackCount)- 默认为1(不可堆叠)
            if (data.StackCount.HasValue)
                ItemHelper.SetItemProperty(item, ItemSettableProperty.StackCount, data.StackCount.Value);

            // 重量(weight)
            if (data.Weight.HasValue)
                ItemHelper.SetItemProperty(item, ItemPrivateField.weight, data.Weight.Value);

            // ==================== 5. 设置价值相关属性 ====================

            // 价格(Price)
            if (data.Price.HasValue)
                ItemHelper.SetItemProperty(item, ItemSettableProperty.Value, data.Price.Value);

            // 品质等级(Quality)
            if (data.Quality.HasValue)
                ItemHelper.SetItemProperty(item, ItemSettableProperty.Quality, data.Quality.Value);

            // 显示品质(DisplayQuality)
            if (data.DisplayQuality.HasValue)
                ItemHelper.SetItemProperty(item, ItemSettableProperty.DisplayQuality, data.DisplayQuality.Value);

            // ==================== 6. 设置耐久度相关属性 ====================

            // 最大耐久度(MaxDurability)
            if (data.MaxDurability.HasValue)
                ItemHelper.SetItemProperty(item, ItemSettableProperty.MaxDurability, data.MaxDurability.Value);

            // 耐久度损失(DurabilityLoss)
            if (data.DurabilityLoss.HasValue)
                ItemHelper.SetItemProperty(item, ItemSettableProperty.DurabilityLoss, data.DurabilityLoss.Value);

            // 当前耐久度(Durability)
            if (data.Durability.HasValue)
                ItemHelper.SetItemProperty(item, ItemSettableProperty.Durability, data.Durability.Value);



            // ==================== 9. 设置标签 ====================

            // 如果指定了覆盖标签，则清空现有标签并使用覆盖标签
            if (data.OverrideTags != null && data.OverrideTags.Length > 0)
            {
                item.Tags.Clear();
                foreach (var tag in data.OverrideTags)
                {
                    if (tag != null)
                        item.Tags.Add(tag);
                }
            }

            // 添加额外标签(无论是否使用了覆盖标签)
            if (data.ExtraTags != null && data.ExtraTags.Length > 0)
            {
                foreach (var tag in data.ExtraTags)
                {
                    if (tag != null)
                        item.Tags.Add(tag);
                }
            }

            // ==================== 10. 设置自定义属性 ====================
            // 首先调用通用提供者（适用于所有物品类型）
            foreach (var provider in genericProviders)
            {
                try
                {
                    provider.ApplyCustomProperties(item, data);
                }
                catch (Exception ex)
                {
                    Debug.LogError($"[CustomItemLib] 通用自定义属性提供者 {provider.GetType().Name} 执行失败: {ex.Message}\n{ex.StackTrace}");
                }
            }

            // 然后根据data的实际类型查找并调用对应的特定类型提供者
            Type dataType = data.GetType();

            // 检查精确类型匹配
            if (typeSpecificProviders.TryGetValue(dataType, out List<ICustomPropertyProvider>? exactTypeProviders))
            {
                foreach (var provider in exactTypeProviders)
                {
                    try
                    {
                        provider.ApplyCustomProperties(item, data);
                    }
                    catch (Exception ex)
                    {
                        Debug.LogError($"[CustomItemLib] 自定义属性提供者 {provider.GetType().Name} 执行失败: {ex.Message}\n{ex.StackTrace}");
                    }
                }
            }

            // 检查基类匹配（确保CustomItemData类型的提供者也能被其子类使用）
            foreach (var kvp in typeSpecificProviders)
            {
                // 跳过已经处理过的精确类型
                if (kvp.Key == dataType)
                    continue;

                // 如果dataType是该类型的子类型，则应用提供者
                if (kvp.Key.IsAssignableFrom(dataType))
                {
                    foreach (var provider in kvp.Value)
                    {
                        try
                        {
                            provider.ApplyCustomProperties(item, data);
                        }
                        catch (Exception ex)
                        {
                            Debug.LogError($"[CustomItemLib] 自定义属性提供者 {provider.GetType().Name} 执行失败: {ex.Message}\n{ex.StackTrace}");
                        }
                    }
                }
            }

            // ==================== 11. 完成 ====================
            Debug.Log($"[CustomItemLib] 创建物品成功: {data.DisplayName ?? "Unknown"} " + $"(TypeID: {data.NewTypeID}, TemplateID: {data.TemplateTypeID})");

            return item;
        }

        // ==================== 配置文件加载方法 ====================

        /// <summary>
        /// 从JSON配置文件加载物品数据
        /// </summary>
        /// <typeparam name="T">数据类型，必须继承自 CustomItemData</typeparam>
        /// <param name="modDirectory">Mod目录路径</param>
        /// <param name="configName">配置文件名（相对于config目录）</param>
        /// <param name="jsonArrayFieldName">JSON中数组字段的名称（默认为"items"）</param>
        /// <returns>加载的配置数据数组，失败返回null</returns>
        public static T[]? LoadFromJson<T>(string modDirectory, string configName)
            where T : CustomItemData
        {
            try
            {
                string configPath = Path.Combine(modDirectory, "Config", $"{configName}.json");
                Debug.Log($"[CustomItemFactory] 加载配置: {configPath}");

                if (!File.Exists(configPath))
                {
                    Debug.LogError($"[CustomItemFactory] 配置文件不存在: {configPath}");
                    return null;
                }

                string jsonContent = File.ReadAllText(configPath);

                // 使用 Newtonsoft.Json 反序列化（支持可空类型）
                ItemConfigRoot<T>? wrapper = JsonConvert.DeserializeObject<ItemConfigRoot<T>>(jsonContent);

                if (wrapper == null || wrapper.items == null || wrapper.items.Length == 0)
                {
                    Debug.LogError($"[CustomItemFactory] 配置为空或解析失败");
                    return null;
                }

                Debug.Log($"[CustomItemFactory] 成功加载 {wrapper.items.Length} 个物品配置");
                return wrapper.items;
            }
            catch (Exception ex)
            {
                Debug.LogError($"[CustomItemFactory] 加载配置失败: {ex.Message}\n{ex.StackTrace}");
                return null;
            }
        }
        /// <summary>
        /// 一站式加载并注册物品
        /// </summary>
        /// <typeparam name="TData">数据类型</typeparam>
        /// <typeparam name="TProvider">属性提供者类型</typeparam>
        /// <param name="registry">物品注册表</param>
        /// <param name="modDirectory">Mod目录路径</param>
        /// <param name="configName">配置文件名</param>
        /// <param name="provider">属性提供者实例（可选）</param>
        /// <returns>成功注册的物品数量</returns>
        public static int LoadAndRegister<TData, TProvider>(
            CustomItemRegistry registry,
            string modDirectory,
            string configName,
            TProvider? provider = null)
            where TData : CustomItemData
            where TProvider : class, ICustomPropertyProvider
        {
            // 加载配置
            TData[]? items = LoadFromJson<TData>(modDirectory, configName);

            if (items == null || items.Length == 0)
            {
                Debug.LogError($"[CustomItemFactory] 加载配置失败: {configName}");
                return 0;
            }

            // 注册属性提供者
            if (provider != null)
            {
                RegisterCustomPropertyProvider<TData>(provider);
            }

            // 批量注册物品
            int count = registry.RegisterBatch(items);
            Debug.Log($"[CustomItemFactory] 自动注册完成: {count}/{items.Length} 个物品");
            return count;
        }
    }
}